package com.lenovo.tool;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Properties;
import java.util.StringTokenizer;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

public class TranslationExporter {
    private static void exportTranslationToFile(File base, File target,
            File toTrans, HashSet<String> exludeArrays) {
        try {
            Document baseDoc = DocumentUtils.openDocument(base);
            HashMap<String, Element> baseMap = XmlResUtil.parseXml(baseDoc,
                    exludeArrays);

            HashMap<String, Element> targetMap;
            if (target.exists()) {
                Document targetDoc = DocumentUtils.openDocument(target);
                targetMap = XmlResUtil.parseXml(targetDoc);
            } else {
                targetMap = new HashMap<String, Element>();
            }

            Document doc = DocumentUtils.createDocument();
            Node root = doc.importNode(baseDoc.getDocumentElement(), false);
            doc.appendChild(root);

            Iterator<String> itor = baseMap.keySet().iterator();
            while (itor.hasNext()) {
                String key = itor.next();
                Element element = (Element)doc.importNode(baseMap.get(key), true);
                
                if (targetMap.containsKey(key)) {
                    String text = targetMap.get(key).getTextContent();
                    System.out.println(text);
                    
                    element.setAttribute("base", text);
                }
                
                root.appendChild(element);
                root.appendChild(doc.createTextNode("\n"));
            }

            if (root.getChildNodes().getLength() > 0
                    && XmlResUtil.createNewFile(toTrans)) {
            	DOMSource source = new DOMSource(doc);
            	
                StreamResult result = new StreamResult(toTrans);
                
                TransformerFactory tf = TransformerFactory.newInstance();
                Transformer transformer = tf.newTransformer();

                transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
                transformer.transform(source, result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (TransformerException e) {
            e.printStackTrace();
        }

    }

    public static void exportTranslations(File baseDir, File outDir,
            String baseLocale, ArrayList<String> localeList,
            ArrayList<String> excludePaths, HashSet<String> excludeArrays) throws IOException {
        XmlResFileFilter filter = new XmlResFileFilter(false);

        for (String path : excludePaths) {
            filter.addExludePath(path);
        }

        ArrayList<File> baseFiles = filter.getLocaleXmlResFiles(baseDir,
                baseLocale);

        int len = baseDir.getAbsolutePath().length();
        for (File base : baseFiles) {
            File parent = base.getParentFile().getParentFile().getParentFile();
            for (String locale : localeList) {
                String tailPath = filter.getXmlResTailPath(locale,
                        base.getName());
                File target = new File(parent, tailPath);
                String path = target.getAbsolutePath().substring(len + 1);

                if (!(filter.shallExclude(path))) {
                    File toTrans = new File(outDir, path);
                    exportTranslationToFile(base, target, toTrans,
                            excludeArrays);
                }
            }
        }
    }

    public static void main(String[] args) {
        if (args.length != 1) {
            System.out.println("please enter the config file name");
            return;
        }

        File configFile = new File(args[0]);
        if (!configFile.exists() || !configFile.isFile()) {
            System.out.println("config file error");
            return;
        }

        try {
            PropConfigHandler handler = new PropConfigHandler();

            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            parser.parse(configFile, handler);

            Properties props = handler.getProps();
            ArrayList<String> excludePathList = handler.getExcludePaths();
            HashSet<String> excludeArrays = handler.getExcludeArrays();

            File baseDir = new File(props.getProperty("basedir"));
            File outDir = new File(props.getProperty("outdir"));
            String baseLocale = props.getProperty("baselocale");
            String locales = props.getProperty("locales");

            if (!baseDir.exists()) {
                System.out.println("config file error");
            }

            ArrayList<String> localeList = new ArrayList<String>();
            if (locales != null) {
                StringTokenizer tokenizer = new StringTokenizer(locales, ",");
                while (tokenizer.hasMoreTokens()) {
                    localeList.add(tokenizer.nextToken());
                }

                exportTranslations(baseDir, outDir, baseLocale,
                        localeList, excludePathList, excludeArrays);
            }

        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
